package com.demo.exception;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.demo.common.BaseRes;
import com.demo.config.RabbitConfig;
import com.demo.pojo.ErrorLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;
import java.util.Set;

/**
 * 全局异常处理
 * 根据全局异常 通过mq保存异常日志
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {


    @Value("${server.port}")
    private String port;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    @ResponseBody
    @ExceptionHandler(Exception.class)
    public String handleException(HttpServletRequest request, Exception e) throws UnknownHostException {
        // 记录错误信息
        ErrorLog errorLog = new ErrorLog();
        errorLog.setMessageid(UUID.fastUUID().toString());
        errorLog.setErrorContent(e.getMessage());
        errorLog.setCreateTime(new Date());
        errorLog.setIp(getIpPort());
        errorLog.setParamContent(getRequestParam(request));
        StackTraceElement stackTraceElement = e.getStackTrace()[0];
        errorLog.setMethodName(stackTraceElement.getMethodName());
        errorLog.setLineNumber(stackTraceElement.getLineNumber());
        errorLog.setServiceid("demo");
        send(JSON.toJSONString(errorLog));
        return "系统错误";
    }


    /**
     * 请求的参数
     *
     * @param request
     * @return
     */
    private String getRequestParam(HttpServletRequest request) {
        //请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        //获得map的key（就是表单中文本域的name集合）
        Set<String> set = parameterMap.keySet();
        for (String name : set) {
            //获得每个文本域所对应的值
            String[] vals = parameterMap.get(name);
            System.out.print("name:" + name);
            for (String val : vals) {
                System.out.print(val + " ");
                return val;
            }
        }
        return null;
    }


    /**
     * 发送消息
     *
     * @param
     * @param message 消息
     */
    public void send(String message) {
        CorrelationData correlationId = new CorrelationData(UUID.fastUUID().toString());
        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE, RabbitConfig.ROUTINGKEY1,
                message, correlationId);
    }

    /**
     * 获取端口号
     *
     * @return
     * @throws UnknownHostException
     */
    private String getIpPort() throws UnknownHostException {
        InetAddress localHost = Inet4Address.getLocalHost();
        return localHost.getHostAddress() + ":" + port;
    }


    public static void main(String[] args) {
        try {
            int i = 1 / 0;
        } catch (Exception ex) {
            ex.printStackTrace();
//System.out.println(ex.getStackTrace()[0].getLineNumber());///getFileName() ;
            StackTraceElement stackTraceElement = ex.getStackTrace()[0];
            String message = ex.getMessage();
            System.out.println("errorContent=" + message);
            System.out.println("File=" + stackTraceElement.getFileName());
            System.out.println("Line=" + stackTraceElement.getLineNumber());
            System.out.println("Method=" + stackTraceElement.getMethodName());
        }
    }

    /**
     * 自定义异常
     */
    @ExceptionHandler(RrException.class)
    public BaseRes handleRRException(RrException e) {
        BaseRes res = new BaseRes();
        res.setCode(String.valueOf(e.getCode()));
        res.setMsg(e.getMessage());
        return res;
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public BaseRes handleDuplicateKeyException(DuplicateKeyException e) {
        log.error(e.getMessage(), e);
        return BaseRes.error("数据库中已存在该记录");
    }

    @ExceptionHandler(InvalidDataAccessResourceUsageException.class)
    public BaseRes handleDuplicateKeyException(InvalidDataAccessResourceUsageException e) {
        log.error(e.getMessage(), e);
        return BaseRes.error("演示环境禁止插插插");
    }


    /**
     * 异常处理参数
     */
    @ExceptionHandler(value = {BindException.class})
    public BaseRes bindException(BindException e) {
        return BaseRes.error(e.getAllErrors().toString());
    }
}
